﻿
Imports std

Public Module ProHttpS

    Public Const defaultConfigfile As String = "ProHttpS.ini"
    Public WithEvents config As configMonitor = Nothing
    Public WithEvents server As processorHttpServer = Nothing

    Public Sub startservice()
        assert(Not config Is Nothing, "have not opened configuration")
        If server Is Nothing Then
            server = New processorHttpServer()
        Else
            server.processors().clear()
        End If
        server.addports(config.parameter(configNaming.ProHttpS.name, configNaming.ProHttpS.port _
                                         , configNaming.defaultValue.ProHttpS.port))
        server.addRequestProcessor(New staticrequest())
        server.addRequestProcessor(New buildInfoPage())
        server.addRequestProcessor(New favicon())

        Dim apps As vector(Of String) = Nothing
        Dim namespaces As vector(Of String) = Nothing
        Dim classes As vector(Of String) = Nothing
        config.readlist(configNaming.ProHttpS.name, configNaming.ProHttpS.app, apps)
        config.readlist(configNaming.ProHttpS.name, configNaming.ProHttpS.namespace, namespaces)
        config.readlist(configNaming.ProHttpS.name, configNaming.ProHttpS.class, classes)

        assert(apps.size() = namespaces.size() AndAlso apps.size() = classes.size() _
               , "do not have matched app/namespace/class definition in configuration.")

        Dim i As Int64
        Dim curdir As String = Nothing
        curdir = Environment.CurrentDirectory()
        For i = 0 To apps.size() - 1
            Dim t As Type = Nothing
            If loadclass(apps(i), namespaces(i), classes(i), t) Then
                Environment.CurrentDirectory = parentpath(apps(i))
                server.addRequestProcessor(alloc(t), config)
                Environment.CurrentDirectory = curdir
            End If
        Next

        server.start(config.parameter(configNaming.ProHttpS.name, configNaming.ProHttpS.threadcount _
                                       , configNaming.defaultValue.ProHttpS.threadcount))
    End Sub

    Public Sub stopservice()
        If Not server Is Nothing Then
            server.stop()
        End If
    End Sub

    Public Sub shutdown()
        stopservice()
        finishmain()
    End Sub

    Public Sub monitor()
        While Not consoleExtSignal() AndAlso (server.health() OrElse config.refreshing())
            sleep()
        End While

        If consoleExtSignal() Then
            raiseError("caught console ext signal, shutdown...")
        ElseIf Not server.health() Then
            raiseError("caught httpserver error.", errorHandle.errorType.critical)
        Else
            raiseError("unhandled error.", errorHandle.errorType.critical)
        End If
        shutdown()
    End Sub

    Public Sub unhandledException(ByVal ex As Exception)
        shutdown()
    End Sub

    Public Sub main(ByVal args() As String)
        startmain(AddressOf unhandledException)
        Dim configfile As String = Nothing
        If args.Length() > 0 Then
            configfile = args(0)
        Else
            configfile = defaultConfigfile
        End If
        config = New configMonitor()
        assert(config.open(configfile), "cannot open configuration file " + configfile)

        startservice()
        monitor()
        shutdown()
    End Sub

    Private Sub config_ConfigChanged() Handles config.ConfigChanged
        stopservice()
        startservice()
    End Sub

    Private Sub server_receive(ByVal context As httpContext) Handles server.receive
        assert(False, "server.receive event should not be called in processorHttpServer")
    End Sub
End Module
